import { ref } from "vue";
import { useModal } from "./useModal";
import { useForm } from "./useForm";
import utils from "xe-utils";
import { ElMessage as Message, ElMessageBox } from "element-plus";

const ACTIONS = {
  view: "查看",
  edit: "编辑",
  add: "创建",
};

interface CrudOptions<T> {
  name: string;
  initForm?: T;
  doCreate: Function;
  doDelete: Function;
  doUpdate: Function;
  refresh: Function;
  doGet?: Function;
}

interface CurdOpenDto {
  action: keyof typeof ACTIONS;
  title: string;
  row: any;
  onOk?: Function;
}

export function useCrud<T>({
  initForm,
  name,
  doDelete,
  refresh,
  doCreate,
  doUpdate,
  doGet,
}: CrudOptions<T>) {
  const modalAction = ref<keyof typeof ACTIONS>("add");
  const { modalRef, okLoading } = useModal();
  const { formRef, formModel, validation } = useForm<T>(
    initForm || ({} as any),
  );

  const rowId = ref<string | null>(null);

  function handleAdd(row?: any, title: string = "", onOk?: Function) {
    handleOpen({ action: "add", title, row: { ...initForm, ...row }, onOk });
  }

  /** 修改 */
  async function handleEdit(_row: any, title: string = "") {
    let row = { ..._row };
    if (doGet) {
      const { data } = await doGet(_row.id);
      row = { ...data };
    }
    rowId.value = row.id;
    handleOpen({ action: "edit", title, row });
  }

  /** 查看 */
  async function handleView(_row: any, title: string = "") {
    let row = { ..._row };
    if (doGet) {
      const { data } = await doGet(_row.id);
      row = { ...data };
    }
    rowId.value = row.id;
    handleOpen({ action: "view", title, row });
  }

  function handleOpen(options: CurdOpenDto) {
    const { row, action, onOk, title } = options;
    modalAction.value = action;
    formModel.value = utils.destructuring(formModel.value, { ...row });
    modalRef.value?.open({
      ...options,
      async onOk() {
        if (typeof onOk === "function") {
          return await onOk(formModel.value);
        } else {
          return await handleSave();
        }
      },
      title: title || (ACTIONS[action] || "") + name,
    });
  }

  async function handleSave(action?: string) {
    if (!action && !["edit", "add"].includes(modalAction.value)) {
      return false;
    }

    try {
      await validation();
    } catch (e) {
      return false;
    }
    const actions: any = {
      add: {
        api: () => doCreate(JSON.parse(JSON.stringify(formModel.value))),
        cb: () => Message.success("新增成功"),
      },
      edit: {
        api: () =>
          doUpdate(rowId.value, JSON.parse(JSON.stringify(formModel.value))),
        cb: () => Message.success("保存成功"),
      },
    };

    const target = action ? actions[action!] : actions[modalAction.value];

    try {
      okLoading.value = true;
      const data = await target.api();
      target.cb();

      okLoading.value = false;

      data && refresh(data);
    } catch (error: any) {
      okLoading.value = false;
      return false;
    }
  }

  /** 删除 */
  function handleDelete(id: string, confirmOptions: any = {}) {
    if (!id) return;
    ElMessageBox.confirm("确定删除？", "提示", confirmOptions).then(
      async () => {
        const data = await doDelete(id);
        Message.success("删除成功");
        refresh(data);
      },
    );
  }

  return {
    modalRef,
    formRef,
    modalAction,
    formModel,
    okLoading,
    validation,
    handleAdd,
    handleOpen,
    handleSave,
    handleView,
    handleEdit,
    handleDelete,
  };
}
